﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FEM.Result;

namespace PBSD_Development
{
    /// <summary>
    /// 塔楼对象
    /// </summary>
    public class TowerObj
    {
        /// <summary>
        /// 塔楼对象
        /// </summary>
        private Tower tower { set; get; }

        /// <summary>
        /// 楼层列表
        /// </summary>
        private List<StoreyObj> storeyList { set; get; }

        /// <summary>
        /// 塔楼序号
        /// </summary>
        public int TowerIndex
        {
            get
            {
                return this.tower.TowerIndex;
            }
        }

        /// <summary>
        /// 塔楼所有楼层
        /// </summary>
        /// <returns> 楼层列表 </returns>
        public List<StoreyObj> GetStoreyList()
        {
            return this.storeyList;
        }

        /// <summary>
        /// 底部楼层
        /// </summary>
        /// <returns></returns>
        public StoreyObj GetBottomStorey()
        {
            return this.storeyList.First();
        }

        /// <summary>
        /// 顶部楼层
        /// </summary>
        /// <returns></returns>
        public StoreyObj GetTopStorey()
        {
            return this.storeyList.Last();
        }

        /// <summary>
        /// 塔楼内楼层查询
        /// </summary>
        /// <param name="storeyIndex"> 楼层编号 </param>
        /// <param name="storeyObj"> 楼层对象 </param>
        /// <returns> 是否存在 </returns>
        public bool GetStorey(int storeyIndex, out StoreyObj storeyObj)
        {
            //初始化
            storeyObj = new StoreyObj();
            //遍历楼层
            foreach(var storey in this.storeyList)
            {
                if(storey.StoreyIndex == storeyIndex)
                {
                    storeyObj = storey;
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 获得楼层响应
        /// </summary>
        /// <param name="loadCase"></param>
        /// <param name="reaction"></param>
        /// <returns></returns>
        public double GetMaxReaction(LoadCaseObj loadCase, StoreyReaction reaction)
        {
            var responseList = (from storey in this.storeyList select storey.GetMaxReaction(loadCase, reaction)).ToList();
            return responseList.Count == 0 ? 0 : responseList.Max();
        }

        /// <summary>
        /// 获得楼层响应
        /// </summary>
        /// <param name="loadCase"></param>
        /// <param name="reaction"></param>
        /// <returns></returns>
        public double GetMaxReaction(LoadCaseObj loadCase, StoreyReaction reaction, bool isX)
        {
            var responseList = (from storey in this.storeyList select storey.GetMaxReaction(loadCase, reaction, isX)).ToList();
            return responseList.Count == 0 ? 0 : responseList.Max();
        }

        /// <summary>
        /// 塔楼最大层间位移角所在楼层
        /// </summary>
        /// <param name="loadCase"> 工况 </param>
        /// <param name="isX"> X向/Y向层间位移角 </param>
        /// <returns> 层间位移角 </returns>
        public bool GetMaxDriftStorey(LoadCaseObj loadCase, bool isX, out StoreyObj storey)
        {
            //层间位移角初始化
            storey = new StoreyObj();
            //层间位移角存在
            if (this.storeyList.Count == 0) return false;
            //获得最大层间位移角对象
            storey = this.storeyList.Aggregate((st1, st2) =>
            st1.GetMaxReaction(loadCase, StoreyReaction.Drift, isX) > st2.GetMaxReaction(loadCase, StoreyReaction.Drift, isX) ? st1 : st2);
            //最大层间位移角存在
            return true;
        }

        /// <summary>
        /// 塔楼最大层间位移角所在楼层
        /// </summary>
        /// <param name="loadCase"> 工况 </param>
        /// <returns> 层间位移角 </returns>
        public bool GetMaxDriftStorey(LoadCaseObj loadCase, out StoreyObj storey)
        {
            //层间位移角初始化
            storey = new StoreyObj();
            //层间位移角存在
            if (this.storeyList.Count == 0) return false;
            //获得最大层间位移角对象
            storey = this.storeyList.Aggregate((st1, st2) =>
            st1.GetMaxReaction(loadCase, StoreyReaction.Drift) > st2.GetMaxReaction(loadCase, StoreyReaction.Drift) ? st1 : st2);
            //最大层间位移角存在
            return true;
        }

        /// <summary>
        /// 塔楼最大层间位移角所在楼层
        /// </summary>
        /// <param name="loadCase"> 工况 </param>
        /// <param name="isX"> X向/Y向层间位移角  </param>
        /// <returns> 最大层间位移角所在楼层 </returns>
        public int GetMaxDriftStoreyIndex(LoadCaseObj loadCase, bool isX)
        {
            //获得最大层间位移角对象
            StoreyObj storey;
            if (!this.GetMaxDriftStorey(loadCase, isX, out storey)) return -999;
            else return storey.StoreyIndex;
        }

        /// <summary>
        /// 塔楼最大层间位移角所在楼层
        /// </summary>
        /// <param name="loadCase"> 工况 </param>
        /// <returns> 最大层间位移角所在楼层 </returns>
        public int GetMaxDriftStoreyIndex(LoadCaseObj loadCase)
        {
            //获得最大层间位移角对象
            StoreyObj storey;
            if (!this.GetMaxDriftStorey(loadCase, out storey)) return -999;
            else return storey.StoreyIndex;
        }

        /// <summary>
        /// 塔楼最大顶点位移
        /// </summary>
        /// <param name="loadCase"> 工况 </param>
        /// <param name="isX">  X向/Y向顶点位移 </param>
        /// <returns> 位移 </returns>
        public double GetTopDisp(LoadCaseObj loadCase)
        {
            return this.GetTopStorey().GetMaxReaction(loadCase, StoreyReaction.Disp);
        }

        /// <summary>
        /// 塔楼最大顶点位移
        /// </summary>
        /// <param name="loadCase"> 工况 </param>
        /// <param name="isX">  X向/Y向顶点位移 </param>
        /// <returns> 位移 </returns>
        public double GetTopDisp(LoadCaseObj loadCase, bool isX)
        {
            return this.GetTopStorey().GetMaxReaction(loadCase, StoreyReaction.Disp, isX);
        }

        /// <summary>
        /// 最大基底剪力
        /// </summary>
        /// <param name="loadCase"> 工况 </param>
        /// <param name="isX">  X向/Y向基底剪力 </param>
        /// <returns> 基底剪力 </returns>
        public double GetBottomForce(LoadCaseObj loadCase, bool isX)
        {
            return this.GetBottomStorey().GetMaxForce(loadCase, isX);
        }

        /// <summary>
        /// 最大基底倾覆弯矩
        /// </summary>
        /// <param name="loadCase"> 工况 </param>
        /// <param name="isX"> X向/Y向倾覆弯矩 </param>
        /// <returns> 倾覆弯矩 </returns>
        public double GetBottomMoment(LoadCaseObj loadCase, bool isX)
        {
            return this.GetBottomStorey().GetMaxMoment(loadCase, isX);
        }

        /// <summary>
        /// 单元组各楼层构件性能状态占比
        /// </summary>
        /// <param name="loadcase"> 工况 </param>
        /// <param name="groupObj"> 单元组 </param>
        /// <returns> 各楼层构件性能状态占比 </returns>
        public Dictionary<int, List<double>> GetStoreyDeformPerformRatio(LoadCaseObj loadcase, ElementGroupObj groupObj)
        {
            return groupObj.GetStoreyDeformPerformRatio(loadcase, this);
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public TowerObj()
        {
            //初始化
            this.storeyList = new List<StoreyObj>();
        }

        /// <summary>
        /// 构造塔楼
        /// </summary>
        /// <param name="tower"></param>
        /// <param name="result"></param>
        public TowerObj(Tower tower, FEMResult result): this()
        {
            //获得塔楼
            this.tower = tower;
            //遍历塔楼的楼层创建数据
            foreach(var storey in this.tower.StoreyList)
            {
                this.storeyList.Add(new StoreyObj(this, storey, result));
            }
        }
    }
}
